#include <plugins_manager_appfwk/qls_plugins_manager_appfwk.h>

#include <QSettings>
#include <QTextCodec>

#include <plugins_manager_appfwk/qls_vtabbar.h>
#include <plugins_manager_appfwk/qls_plugins_manager_tablewidget.h>
#include <log/qls_log.h>
#include <plugins_manager/qls_plugins_manager_pool.h>
#include <themes_manager/qls_themes_manager.h>

static const int STACKEDWIDGET_MIN_WIDTH = 618;
static const int STACKEDWIDGET_MIN_HEIGHT = 174;

QLsPluginsManagerAppfwk::QLsPluginsManagerAppfwk(QWidget *parent)
    : QTabWidget(parent),
      pluginsManagerTableWidget(new QLsPluginsManagerTableWidget),
      hTabBar(new QTabBar), vTabBar(new QLsVTabBar),
      m_tabWidgetMiniWidth(STACKEDWIDGET_MIN_WIDTH),
      m_tabWidgetMiniHeight(STACKEDWIDGET_MIN_HEIGHT),
      m_isShowPluginsManagerTab(false), m_tabStyle(QLsTabStyle::NORTH),
      m_bHideTabBar(false)
{
    /* 主界面初始化 */
    HomeInit();
}

QLsPluginsManagerAppfwk::~QLsPluginsManagerAppfwk()
{
    QLsPluginsManagerPool::GetInstance().DestroyPluginsManager(
        QLsPluginsManagerPool::GetInstance().GetPluginsManagerByPluginsDir(
            m_pluginsDir));

    delete pluginsManagerTableWidget;
}

QLsPluginsManagerAppfwk::QLsTabStyle QLsPluginsManagerAppfwk::tabStyle() const
{
    return m_tabStyle;
}

void QLsPluginsManagerAppfwk::setTabStyle(const QLsTabStyle &tabStyle)
{
    if (m_tabStyle == tabStyle)
        return;

    QSize changeSize(0, 0); /* 样式修改前尺寸 */
    switch (tabStyle) {
    case QLsTabStyle::NORTH: /* 北(正常) */
    {
        switch (m_tabStyle) {
            //		case QLsTabStyle::NORTH:
            //			break;
        /* 从左右变为上下 */
        case QLsTabStyle::WEST: {
            int preWidth = tabBar()->width();
            setTabBar(hTabBar);
            setTabPosition(QTabWidget::North);
            tabBar()->adjustSize();
            adjustSize();
            changeSize.setWidth(-preWidth);
            changeSize.setHeight(tabBar()->height());
            break;
        }
        default:
            break;
        }
        break;
    }
    case QLsTabStyle::WEST: /* 西(左侧 竖排 文字横向) */
    {
        switch (m_tabStyle) {
        /* 从上下变为左右 */
        case QLsTabStyle::NORTH: {
            int preHeight = tabBar()->height();
            setTabBar(vTabBar);
            setTabPosition(QTabWidget::West);
            tabBar()->adjustSize();
            adjustSize();
            changeSize.setWidth(tabBar()->width());
            changeSize.setHeight(-preHeight);
            break;
        }
            //		case QLsTabStyle::WEST:
            //			break;
        default:
            break;
        }
        break;
    }
    default:
        break;
    }

    /* 更新最小尺寸 */
    if (changeSize.width() || changeSize.height()) {
        m_tabWidgetMiniWidth += changeSize.width();
        m_tabWidgetMiniHeight += changeSize.height();
        setMinimumSize(m_tabWidgetMiniWidth, m_tabWidgetMiniHeight);
        resize(qMax(width(), m_tabWidgetMiniWidth),
               qMax(height(), m_tabWidgetMiniHeight));
        emit sigChangeMinimumSize(changeSize);
    }

    m_tabStyle = tabStyle;
}

/* 当前主题名 */
QString QLsPluginsManagerAppfwk::curThemeName() const
{
    return m_curThemeName;
}

void QLsPluginsManagerAppfwk::setCurThemeName(const QString &curThemeName)
{
    m_curThemeName = curThemeName;
}

/* 插件路径 */
QString QLsPluginsManagerAppfwk::pluginsDir() const
{
    return m_pluginsDir;
}

void QLsPluginsManagerAppfwk::setPluginsDir(const QString &pluginsDir)
{
    if (m_pluginsDir == pluginsDir)
        return;
    m_pluginsDir = pluginsDir;
    m_pluginsIniDir = QString("ini/%1.ini").arg(pluginsDir);

    /* 获取本地插件信息 */
    QLsPluginsManager *pluginsManager =
        QLsPluginsManagerPool::GetInstance().GetPluginsManagerByPluginsDir(
            m_pluginsDir);
    pluginsManager->RefreshLocalPlugins();

    /* 初始化隐藏插件管理器界面 */
    QSettings settings(m_pluginsIniDir, QSettings::IniFormat);
    settings.setIniCodec(QTextCodec::codecForName("UTF-8"));
    settings.beginGroup("pluginsManager");
    setIsShowPluginsManagerTab(settings.value("show", 0).toUInt());
    setBHideTabBar(settings.value("hideTabBar", 0).toUInt());
    settings.endGroup();
}

/* 插件信息配置文件路径 */
QString QLsPluginsManagerAppfwk::pluginsIniDir() const
{
    return m_pluginsIniDir;
}

/* 获取插件管理器类接口 */
QLsPluginsManagerTableWidget *
QLsPluginsManagerAppfwk::GetPluginsManagerTableWidget()
{
    return pluginsManagerTableWidget;
}

/* 获取插件窗口 */
QWidget *QLsPluginsManagerAppfwk::GetPluginsWidgetByIndex(int index)
{
    return widget(index);
}

QWidget *QLsPluginsManagerAppfwk::GetPluginsWidgetByPluginsName(
    const QString &pluginsName)
{
    return widget(m_pluginsNameList.indexOf(pluginsName));
}

/* 加载全部插件 */
void QLsPluginsManagerAppfwk::LoadAllPlugin()
{
    /* 初始化加载全部插件 */
    QLsPluginsManager *pluginsManager =
        QLsPluginsManagerPool::GetInstance().GetPluginsManagerByPluginsDir(
            m_pluginsDir);
    QSettings settings(m_pluginsIniDir, QSettings::IniFormat);
    settings.setIniCodec(QTextCodec::codecForName("UTF-8"));
    for (PluginInfo info : pluginsManager->GetPluginsList()) {
        settings.beginGroup(info.m_filename.toUtf8().data());
        if (settings.value("loaded", 0).toUInt()) {
            slotPluginLoad(info);
        }
        pluginsManagerTableWidget->AddPluginWidget(info);
        settings.endGroup();
    }

    /* 检查插件 */
    if (!pluginsManager->CheckMustLoadPlugins())
        for (QString mustLoadPlugin : pluginsManager->mustLoadButDisload()) {
            QLOG_INFO() << "加载插件" << mustLoadPlugin << "失败";
        }
}

/* 是否显示插件管理器界面 */
bool QLsPluginsManagerAppfwk::isShowPluginsManagerTab() const
{
    return m_isShowPluginsManagerTab;
}

void QLsPluginsManagerAppfwk::setIsShowPluginsManagerTab(
    bool isShowPluginsManagerTab)
{
    if (m_isShowPluginsManagerTab == isShowPluginsManagerTab)
        return;
    m_isShowPluginsManagerTab = isShowPluginsManagerTab;

    if (m_bHideTabBar)
        m_isShowPluginsManagerTab = false;

    /* 显示 */
    if (m_isShowPluginsManagerTab) {
        //		QSize tabBarPreSize(tabBar()->size());
        QFontMetrics nameFontWidth(tabBar()->font());
        QString nameElideNote =
            nameFontWidth.elidedText(tr("插件管理"), Qt::ElideRight, 60 * 1);

        insertTab(0, pluginsManagerTableWidget,
                  QIcon("icon/plugins/manager-8A8A8A.png"), nameElideNote);
        setTabToolTip(0, tr("插件管理"));
        m_pluginsNameList.insert(0, "插件管理");
        //		UpdateMinimumSize(tabBarPreSize);
    }
    /* 隐藏 */
    else {
        removeTab(0);
        m_pluginsNameList.removeAt(0);
    }
}

/* 主题管理器 */
QLsThemesManager *QLsPluginsManagerAppfwk::themesManager() const
{
    return QLsPluginsManagerPool::GetInstance()
        .GetPluginsManagerByPluginsDir(m_pluginsDir)
        ->themesManager();
}

/* 加载、卸载插件的槽函数 */
void QLsPluginsManagerAppfwk::slotPluginLoad(PluginInfo &pluginInfo)
{
    QLsPluginsManager *pluginsManager =
        QLsPluginsManagerPool::GetInstance().GetPluginsManagerByPluginsDir(
            m_pluginsDir);

    /* 卸载插件 */
    if (pluginInfo.m_isLoaded) {
        /* 移除工具按钮和堆栈窗口 */
        RemoveWindows(pluginInfo);

        /* 卸载插件 */
        if (!pluginsManager->UnloadPlugin(pluginInfo)) {
            /* 卸载失败，再把 工具按钮和堆栈窗口 挂回去 */
            PopulateWindows(pluginInfo);
            QLOG_WARN() << "卸载插件"
                        << pluginInfo.m_interfaceInfo->m_name.toUtf8().data()
                        << "失败";
            return;
        }

        QLOG_INFO() << "卸载插件"
                    << pluginInfo.m_interfaceInfo->m_name.toUtf8().data()
                    << "成功";
    }
    /* 加载插件 */
    else {
        /* 加载插件 */
        if (!pluginsManager->LoadPlugin(pluginInfo)) {
            /* 加载失败 */
            QLOG_WARN() << "加载插件"
                        << pluginInfo.m_interfaceInfo->m_name.toUtf8().data()
                        << "失败";
            return;
        }

        /* 生成工具按钮和堆栈窗口 */
        PopulateWindows(pluginInfo);

        QLOG_INFO() << "加载插件"
                    << pluginInfo.m_interfaceInfo->m_name.toUtf8().data()
                    << "成功";
    }

    /* 更新加载状态 */
    emit sigLoadRes(pluginInfo);
}

/* 插件的最小尺寸变化的槽函数 */
void QLsPluginsManagerAppfwk::slotPluginsChangeMinimumSize()
{
    /* 更新最新尺寸 */
    UpdateMinimumSize();
}

/* 主界面初始化 */
void QLsPluginsManagerAppfwk::HomeInit()
{
    hTabBar->setStyleSheet("QTabBar::tab{"
                           "min-height: 25px;"
                           "min-width: 60px;"
                           "}");
    setTabBar(hTabBar);

    /* 嵌入窗口大小初始化，重设大小，解决 qss样式更改 及 代码初始化
     * 导致的窗口大小嵌入冲突 */
    if (width() < m_tabWidgetMiniWidth || height() < m_tabWidgetMiniHeight)
        resize(m_tabWidgetMiniWidth, m_tabWidgetMiniHeight);

    connect(pluginsManagerTableWidget, &QLsPluginsManagerTableWidget::sigLoad,
            this, &QLsPluginsManagerAppfwk::slotPluginLoad);
    connect(this, &QLsPluginsManagerAppfwk::sigLoadRes,
            pluginsManagerTableWidget,
            &QLsPluginsManagerTableWidget::slotLoadRes);
}

/* 填充插件窗口 */
void QLsPluginsManagerAppfwk::PopulateWindows(const PluginInfo &info)
{
    /* ----- 界面 ----- */
    QWidget *widget = info.m_interface->GetPluginWidget();

    /* 过长显示省略号 */
    QFontMetrics nameFontWidth(tabBar()->font());
    QString nameElideNote = nameFontWidth.elidedText(
        info.m_interfaceInfo->m_name, Qt::ElideRight, 60 * 1);

    addTab(widget, QIcon(info.m_interfaceInfo->m_logoPath), nameElideNote);
    setTabToolTip(count() - 1, info.m_interfaceInfo->m_name);
    m_pluginsNameList.append(info.m_interfaceInfo->m_name);

    /* 主题信号槽关联并发送当前主题 */
    QLsThemesManager *themesManager =
        QLsPluginsManagerPool::GetInstance()
            .GetPluginsManagerByPluginsDir(m_pluginsDir)
            ->themesManager();
    info.m_interface->connetChangeTheme(themesManager);
    emit themesManager->sigChangeTheme(m_curThemeName);

    /* 绑定 最小尺寸变化 的信号槽 */
    info.m_interface->connectChangeMinimumSize(this);

    /* 更新最新尺寸 */
    UpdateMinimumSize();

    QSettings settings(m_pluginsIniDir, QSettings::IniFormat);
    settings.setIniCodec(QTextCodec::codecForName("UTF-8"));
    settings.beginGroup(info.m_filename);
    settings.setValue("logoPath",
                      info.m_interfaceInfo->m_logoPath.toUtf8().data());
    settings.setValue("information",
                      info.m_interfaceInfo->m_information.toUtf8().data());
    settings.setValue("loaded", 1);
    settings.setValue("level", info.m_interfaceInfo->m_level);
    settings.setValue("version",
                      info.m_interfaceInfo->m_version.toUtf8().data());
    settings.endGroup();
}

/* 移除插件窗口 */
void QLsPluginsManagerAppfwk::RemoveWindows(const PluginInfo &info)
{
    /* 移除堆栈窗口 */
    QWidget *pluginWidget = info.m_interface->GetPluginWidget();
    int index = indexOf(pluginWidget);
    removeTab(index);
    disconnect(pluginWidget, 0, 0, 0);
    m_pluginsNameList.removeAt(index);

    /* 更新最新尺寸 */
    UpdateMinimumSize();

    QSettings settings(m_pluginsIniDir, QSettings::IniFormat);
    settings.setIniCodec(QTextCodec::codecForName("UTF-8"));
    settings.beginGroup(info.m_filename);
    settings.setValue("loaded", 0);
    settings.endGroup();
}

/* 更新最新尺寸 */
void QLsPluginsManagerAppfwk::UpdateMinimumSize()
{
    /* 更新最小尺寸 最小尺寸是所有窗口中最大的尺寸 */
    tabBar()->adjustSize();
    int minWidth = STACKEDWIDGET_MIN_WIDTH;
    int minHeight = STACKEDWIDGET_MIN_HEIGHT;
    int pages = count();
    for (int i = 0; i < pages; i++) {
        QWidget *page = widget(i);
        minWidth = qMax(minWidth, page->minimumWidth());
        minHeight = qMax(minHeight, page->minimumHeight() + 35);
    }

    /* 子窗口尺寸变化及最小尺寸变化 */
    QSize changeSize(minWidth - m_tabWidgetMiniWidth,
                     minHeight - m_tabWidgetMiniHeight);
    m_tabWidgetMiniWidth = minWidth;
    m_tabWidgetMiniHeight = minHeight;
    switch (m_tabStyle) {
    /* 上下不增加宽高 */
    case QLsTabStyle::NORTH:
        break;
    /* 左右只增加宽度 */
    case QLsTabStyle::WEST:
        m_tabWidgetMiniWidth += tabBar()->width();
        changeSize.setWidth(changeSize.width() + tabBar()->width());
        break;
    default:
        break;
    }
    setMinimumSize(m_tabWidgetMiniWidth, m_tabWidgetMiniHeight);

    /* 大小变化的信号 */
    emit sigChangeMinimumSize(changeSize);

    /* 更新当前尺寸 */
    resize(qMax(width(), m_tabWidgetMiniWidth),
           qMax(height(), m_tabWidgetMiniHeight));
}

/* 是否隐藏标签栏 */
bool QLsPluginsManagerAppfwk::bHideTabBar() const
{
    return m_bHideTabBar;
}

void QLsPluginsManagerAppfwk::setBHideTabBar(bool bHideTabBar)
{
    if (m_bHideTabBar == bHideTabBar)
        return;
    m_bHideTabBar = bHideTabBar;

    tabBar()->hide();
    setIsShowPluginsManagerTab(false);
}
